#include <string>
#include "Channel.h"
#include "PollDispatcher.h"
#include "EventLoop.h"

PollDispatcher::PollDispatcher(EventLoop *evLoop) : Dispatcher(evLoop)
{
    m_maxFd = 0;
    m_fds = new struct pollfd[m_maxNode];
    for (int32_t i = 0; i < m_maxNode; i++)
    {
        m_fds[i].fd = -1;
        m_fds[i].events = 0;
        m_fds[i].revents = 0;
    }
    m_name = "Poll";
}

PollDispatcher::~PollDispatcher()
{   
    delete[] m_fds;
}

int32_t PollDispatcher::add()
{
    int32_t i = 0;
    for (; i < m_maxNode; i++)
    {
        if (m_fds[i].fd == -1)
        {
            m_fds[i].fd = m_channel->getSocket();
            if (m_channel->getEvent() & static_cast<int>(FDEvent::ReadEvent))
            {
                m_fds[i].events = POLLIN;
            }
            if (m_channel->getEvent() & static_cast<int>(FDEvent::WriteEvent))
            {
                m_fds[i].events |= POLLOUT;
            }
            m_maxFd = (m_maxFd > m_channel->getSocket()) ? m_maxFd : m_channel->getSocket();
            break;
        }
        if (i == m_maxNode)
        {
            return -1;
        }
    }
    return 0;
}

int32_t PollDispatcher::remove()
{
    int32_t i = 0;
    for (; i < m_maxNode; i++)
    {
        if (m_fds[i].fd == m_channel->getSocket())
        {
            m_fds[i].fd = -1;
            m_fds[i].events = 0;
            m_fds[i].revents = 0;
            break;
        }
    }
    //通过channel释放对于的tcpConnection资源
    m_channel->destroyCallback(const_cast<void *>(m_channel->getArg()));
    if (i == m_maxNode)
    {
        return -1;
    }
    return 0;
}

int32_t PollDispatcher::modify()
{
    int32_t i = 0;
    for (; i < m_maxNode; i++)
    {
        if (m_fds[i].fd == m_channel->getSocket())
        {
            if (m_channel->getEvent() & static_cast<int>(FDEvent::ReadEvent))
            {
                m_fds[i].events = POLLIN;
            }
            if (m_channel->getEvent() & static_cast<int>(FDEvent::WriteEvent))
            {
                m_fds[i].events |= POLLOUT;
            }
            break;
        }
        if (i == m_maxNode)
        {
            return -1;
        }
    }
    return 0;;
}

int32_t PollDispatcher::dispatch(int timeout)
{
    int32_t count = poll(m_fds, m_maxFd + 1, timeout * 1000);
    if (count < 0)
    {
        perror("poll error");
    }
    printf(" name = %s count = %d m_maxFd = %d\n",m_evLoop->getThreadName().data(), count, m_maxFd);
    for (int32_t i = 0; i <= m_maxFd; i++)
    {   
        if(m_fds[i].fd == -1)
        {
            continue;
        }
        int32_t events = m_fds[i].revents;
        if (events & (POLLERR | POLLHUP))
        {
            // 对方断开了连接，删除fd
            //  pollRemove(Channel,evLoop);
            continue;
        }
        if (events & POLLIN)
        {
            m_evLoop->eventActive(m_fds[i].fd, (int)FDEvent::ReadEvent);
        }
        if (events & POLLOUT)
        {
            m_evLoop->eventActive(m_fds[i].fd, (int)FDEvent::WriteEvent);
        }
    }
    
    return 0;
}
